#include "CTileLayer.h"



CTileLayer::CTileLayer(CTexture* pImage , int Column, int Row, int CellSize)
{
	m_pTileImage		= pImage;
	m_nCellSize			= CellSize;
	m_nNumCellWidth		= ( g_ScreenWidth / CellSize ) + 1;
	m_nNumCellHeight	= ( g_ScreenHeight / CellSize ) + 1;
	m_fAngle			= 0.0f;
	m_nCurrType			= MAP_TYPE_NORMAL;

	m_pMap = new MAP[MAP_TYPE_COUNT];
	
	m_pMap[MAP_TYPE_NORMAL].column 			= m_pMap[MAP_TYPE_ROTATE_UP].column		= Column;
	m_pMap[MAP_TYPE_NORMAL].row				= m_pMap[MAP_TYPE_ROTATE_UP].row		= Row;

	m_pMap[MAP_TYPE_ROTATE_LEFT].column 	= m_pMap[MAP_TYPE_ROTATE_RIGHT].column	= Row;
	m_pMap[MAP_TYPE_ROTATE_LEFT].row		= m_pMap[MAP_TYPE_ROTATE_RIGHT].row		= Column;

	for ( int i = 0 ; i < MAP_TYPE_COUNT ; ++i )
	{
		InitMap( i , m_pMap[i].column , m_pMap[i].row );
		Reset( i , m_pMap[i].column , m_pMap[i].row );
	}

	D3DXMatrixIdentity(&m_mtxTranform);
}


CTileLayer::~CTileLayer()
{
	Release();
}



//-----------------------------------------//
// Name : Release					       //
// Desc : Free the two dimension map array //
//-----------------------------------------//
void CTileLayer::Release()
{
	for ( int i = 0 ; i < MAP_TYPE_COUNT ; ++i )
		ReleaseMap( i , m_pMap[i].column , m_pMap[i].row );

	if(m_pTileImage)
		m_pTileImage->Release();

	m_pTileImage = NULL;
	D3DXMatrixIdentity(&m_mtxTranform);
}


//----------------------------------//
// Name : InitMap					//
// Desc : Allocate room for our map	//
//----------------------------------//
void CTileLayer::InitMap(int Type, int Col, int Row)
{
	m_pMap[Type].map = new int*[Row];
	for(int i = 0 ; i < Row ; ++i)
		m_pMap[Type].map[i] = new int[Col];
}


//------------------------------------------------------//
// Name : Reset											//
// Desc : Reset entire map , setting all map index to 0 //
//------------------------------------------------------//
void CTileLayer::Reset(int Type , int Col , int Row)
{
	int i , j;
	for( i = 0 ; i < Row ; ++i)
		for( j = 0 ; j < Col ; ++j)
			m_pMap[Type].map[i][j] = 0;
}



//------------------------------------------//
// Name : ReleaseMap						//
// Desc : Free the 2-dimension array memory	//
//------------------------------------------//
void CTileLayer::ReleaseMap(int Type, int Col, int Row)
{
	for ( int i = 0 ; i < Row ; ++i )
		delete[] m_pMap[Type].map[i];
	delete[] m_pMap[Type].map;
}




//------------------------------//
// Name : DrawMap				//
// Desc : Draw entire tiled map //
//------------------------------//
void CTileLayer::DrawMap( RECT area , LPD3DXSPRITE pSpriteHandler )
{
	int x, y;
	int i , j;
	int size1 , size2;

	int leftCell	= area.left / m_nCellSize;
	int leftOffset	= area.left % m_nCellSize;
	int topCell		= area.top / m_nCellSize;
	int topOffset	= area.top % m_nCellSize;

	D3DXMatrixTransformation2D( &m_mtxTranform , NULL , 0.0f , NULL , 
		&D3DXVECTOR2(g_ScreenWidth/2.0f , g_ScreenHeight/2.0f) , D3DXToRadian(m_fAngle) , 
									NULL );
	pSpriteHandler->SetTransform(&m_mtxTranform);

	for (  i = topCell , size1 = i + m_nNumCellHeight ; i < size1 ; ++i)
		for( j = leftCell , size2 = j + m_nNumCellWidth ; j < size2 ; ++j )
		{
			if( i >= m_pMap[m_nCurrType].row || j >= m_pMap[m_nCurrType].column )
				continue;
			if( i < 0 || j < 0 )
				continue;
			if( m_pMap[m_nCurrType].map[i][j] <= 0 )
				continue;
			x = (j - leftCell) * m_nCellSize - leftOffset;
			y = (i - topCell) * m_nCellSize - topOffset;
			DrawCell( m_pMap[m_nCurrType].map[i][j] , x , y  );
		}
}



//---------------------------//
// Name : DrawCell			 //
// Desc : Draw a single cell //
//---------------------------//
void CTileLayer::DrawCell(int TileIndex , int posX , int posY  )
{
	RECT rect;
	rect.left	= (TileIndex - 1 ) * m_nCellSize;
	rect.right	= rect.left + m_nCellSize;
	rect.top	= 0;
	rect.bottom	= rect.top + m_nCellSize;

	m_pTileImage->Draw( posX , posY , 0.0f , &rect , D3DCOLOR_XRGB(255,255,255) );
}



//------------------------------------------------//
// Name : SetTiled							      //
// Desc : Set the image tiled for this tile layer //
//------------------------------------------------//
void CTileLayer::SetTiled(CTexture *pImage)
{
	if(pImage == NULL)
		return;

	if(m_pTileImage)
		m_pTileImage->Release();
	m_pTileImage = NULL;
	m_pTileImage = pImage;
}




//--------------------------------------------//
// Name : SetCell							  //
// Desc : Set the index value for single cell //
//--------------------------------------------//
void CTileLayer::SetCell(int Row , int Column,  int TileIndex)
{
	if( Column >= m_pMap[m_nCurrType].column || Row >= m_pMap[m_nCurrType].row )
		return;

	m_pMap[MAP_TYPE_NORMAL].map[Row][Column]																					= TileIndex;
	m_pMap[MAP_TYPE_ROTATE_RIGHT].map[Column][m_pMap[MAP_TYPE_ROTATE_RIGHT].column - Row - 1]									= TileIndex;
	m_pMap[MAP_TYPE_ROTATE_UP].map[m_pMap[MAP_TYPE_ROTATE_UP].row - Row - 1][m_pMap[MAP_TYPE_ROTATE_UP].column - Column - 1]	= TileIndex;
	m_pMap[MAP_TYPE_ROTATE_LEFT].map[m_pMap[MAP_TYPE_ROTATE_LEFT].row - Column - 1][Row]										= TileIndex;
}



//--------------------------------------//
// Name : SetCurrentType				//
// Desc : Set up the current map type	//
//--------------------------------------//
void CTileLayer::SetCurrentType(MAP_TYPE Type )
{
	m_nCurrType = Type;
}


//--------------------------------------------//
// Name : GetCell							  //
// Desc : Get the value of the input position //
//--------------------------------------------//
int CTileLayer::GetCell(int Column, int Row)
{
	if( Column >= m_pMap[m_nCurrType].column || Row >= m_pMap[m_nCurrType].row )
		return -1;

	return m_pMap[m_nCurrType].map[Row][Column];
}




//----------------------------//
// Name : GetCellSize		  //
// Desc : Get the cell size	  //
//----------------------------//
int CTileLayer::GetCellSize()
{
	return m_nCellSize;
}



//------------------------------------------------//
// Name : GetColumn								  //
// Desc : Get the total column of this Tile layer //
//------------------------------------------------//
int CTileLayer::GetColumn()
{
	return m_pMap[m_nCurrType].column;
}



//---------------------------------------------//
// Name : GetRow							   //
// Desc : Get the total row of this Tile layer //
//---------------------------------------------//
int CTileLayer::GetRow()
{
	return m_pMap[m_nCurrType].row;
}



//-----------------------------------------------------------------//
// Name : isCollision											   //
// Desc : Check the collision of the rect of object with tiled map //
//-----------------------------------------------------------------//
bool CTileLayer::isCollision(RECT objRect)
{
	int i,j;

	int left	= objRect.left / m_nCellSize;
	int right	= ( objRect.right - 1 ) / m_nCellSize;
	int top		= objRect.top / m_nCellSize;
	int bottom	= ( objRect.bottom - 1 ) / m_nCellSize;

	for( i = top ; i <= bottom ; ++i)
		for( j = left ; j <= right ; ++j)
		{
			if( i >= m_pMap[m_nCurrType].row || j >= m_pMap[m_nCurrType].column )
				continue;
			if( i < 0 || j < 0 )
				continue;
			if(m_pMap[m_nCurrType].map[i][j] !=0 )
				return true;
		}

	return false;
}




//----------------------------------------------------------------------//
// Name : LimitRect														//
// Desc : Check the limit area so the camera cant move out of this area	//
//----------------------------------------------------------------------//
bool CTileLayer::LimitRect(RECT camRect)
{
	int i,j;

	int left	= camRect.left / m_nCellSize;
	int right	= ( camRect.right - 1 ) / m_nCellSize;
	int top		= camRect.top / m_nCellSize;
	int bot		= ( camRect.bottom - 1 ) / m_nCellSize;

	for( i = top ; i < bot ; ++i )
	{
		for( j = left ; j < right ; ++j )
		{
			if( i >= m_pMap[m_nCurrType].row || j >= m_pMap[m_nCurrType].column )
				continue;
			if( i < 0 || j < 0 )
				continue;
			if(m_pMap[m_nCurrType].map[i][j] == -1 )
				return true;
		}
	}

	return false;
}




//
//
//
//
void CTileLayer::Rotate()
{
	if( m_nCurrType == MAP_TYPE_ROTATE_RIGHT )
	{
		
	}
	else
	{
		m_fAngle += 1.5f;
		if(m_fAngle >= 90.0f )
		{
			m_nCurrType = MAP_TYPE_ROTATE_RIGHT;
			m_fAngle = 0.0f;
		}
	}
}


//----------------------------------------------------------------------//
// Name : CollisionCheck (Callback function)							//
// Desc : This is call back function for collision checking with object //
//----------------------------------------------------------------------//
bool CTileLayer::CollisionCheck(CAnimatedObject *pObject, LPVOID pContext)
{
	if( ((CTileLayer*)pContext)->isCollision( pObject->GetBoundBox() ) )
		return true;
	
	return false;
}
